#include "Fingerprint-protocol.h"

FingerprintProtocol::FingerprintProtocol(const vector<uint8_t>& packet)
    : packet(packet)
{}

FingerprintProtocol::FingerprintProtocol() {}

// 添加包头
void FingerprintProtocol::addPacketHead(const uint16_t head)
{
    packet.push_back(head >> 8);
    packet.push_back(head & 0xff);
}

// 添加地址
void FingerprintProtocol::addPacketAddr(uint32_t addr)
{
    // head = 0xFFFFFFFF
    for (int i = 0; i < 4; i++) {
        // 存放最高字节
        // 传送时候高字节在前
        packet.push_back(addr >> 24);
        addr = addr << 8;
    }
}

// 添加包标识ID
void FingerprintProtocol::addPacketID(uint8_t pid)
{
    packet.push_back(pid);
}

void FingerprintProtocol::addPacketLen(uint16_t len)
{
    // 压入高字节
    packet.push_back(len >> 8);
    // 压入低字节
    packet.push_back(len & 0xff);
}

// 添加包内容
void FingerprintProtocol::addPacketContent(uint8_t* data, uint32_t size)
{
    for (int i = 0; i < size; i++) {
        packet.push_back(data[i]);
    }
}

/**
 * 添加校验
 */
void FingerprintProtocol::addPacketSum(void)
{
    uint16_t sum = 0;

    for (int i = 6; i < packet.size(); i++) {
        sum += packet[i];
    }
    packet.push_back(sum >> 8);
    packet.push_back(sum & 0xff);
}

void FingerprintProtocol::showPacket(void) const
{

    packet_t* pkt = (packet_t*)packet.data();
    // 4个16进制显示 [0] 成员高字节 [1] 低字节
    printf("packet head : %04x\n", getPacketHead());
    printf("packet addr : %08x\n", getPacketAddr());
    printf("packet id   : %02x\n", getPacketID());
    printf("packet len  : %04x\n", getPacketDataLen() + 2);
    printf("packet data : ");
    uint16_t datalen = getPacketDataLen();
    uint8_t* data    = getPacketData();
    for (int i = 0; i < datalen; i++) {
        printf("%02x ", data[i]);
    }
    printf("\n");
    printf("packet sum: %04x\n", getPacketSum());
}

uint16_t FingerprintProtocol::getPacketHead(void) const
{
    packet_t* pkt = (packet_t*)packet.data();
    return (pkt->head[0] << 8 | pkt->head[1]);
}

// 获取地址
uint32_t FingerprintProtocol::getPacketAddr(void) const
{
    packet_t* pkt = (packet_t*)packet.data();
    uint32_t  packetAddr =
        (pkt->addr[0] << 24) | (pkt->addr[1] << 16) | (pkt->addr[2] << 8) | (pkt->addr[3] << 0);
    return packetAddr;
}

uint8_t FingerprintProtocol::getPacketID(void) const
{
    packet_t* pkt = (packet_t*)packet.data();
    return pkt->pid;
}

uint16_t FingerprintProtocol::getPacketDataLen(void) const
{
    packet_t* pkt = (packet_t*)packet.data();
    return (pkt->len[0] << 8 | pkt->len[1]) - 2;
}

uint8_t* FingerprintProtocol::getPacketData(void) const
{
    packet_t* pkt = (packet_t*)packet.data();
    return pkt->data;
}

uint16_t FingerprintProtocol::getPacketSum(void) const
{
    int packetSize = packet.size();
    return (packet[packetSize - 2] << 8 | packet[packetSize - 1]);
}

bool FingerprintProtocol::isPacketError(void)
{
    uint16_t calcSum = 0;
    for (int i = 6; i < packet.size() - 2; i++) {
        calcSum += packet[i];
    }

    uint16_t packetSum = getPacketSum();
    // printf("calcSum:0x%04x, packetSum:0x%04x\n", calcSum, packetSum);
    return calcSum == packetSum ? false : true;
}

vector<uint8_t> FingerprintProtocol::getPacket(void) const
{
    return packet;
}

FingerprintProtocol FingerprintProtocol::formProtocolPacket(const vector<uint8_t>& packet)
{
    return FingerprintProtocol(packet);
}

// 创建捂手信号
FingerprintProtocol FingerprintProtocol::makeHandshakeProtocol(void)
{

    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x03);
    uint8_t data[] = {0x53};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();
    return protocol;
}

// 1录指纹图像
FingerprintProtocol FingerprintProtocol::makeDetectImageProtocol(void)
{

    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x03);
    uint8_t data[] = {0x01};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();

    return protocol;
}

// 2生成特征码
FingerprintProtocol FingerprintProtocol::makeImageFeatureProtocol(uint8_t bufferID)
{
    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x04);
    uint8_t data[] = {0x02, bufferID};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();
    return protocol;
}

// 特征合成模板
FingerprintProtocol FingerprintProtocol::makeImageTemplateProtocol(void)
{

    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x03);
    uint8_t data[] = {0x05};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();
    return protocol;
}

/**
 * 存储模版
 */
FingerprintProtocol FingerprintProtocol::makeStoreTemplateProtocol(uint16_t pos)
{
    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x06);
    uint8_t data[] = {0x06, 0x01, (uint8_t)(pos >> 8), (uint8_t)(pos & 0xff)};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();
    return protocol;
}

/**
 * 搜索模版指令
 */
FingerprintProtocol FingerprintProtocol::makeSearchFingerprintProtocol(uint16_t startPos,
                                                                       uint16_t n)
{
    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x08);
    uint8_t data[] = {0x04,
                      0x01,
                      (uint8_t)(startPos >> 8),
                      (uint8_t)(startPos & 0xff),
                      (uint8_t)(n >> 8),
                      (uint8_t)(n & 0xff)};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();
    return protocol;
}

/**
 * 删除指纹
 * @param pos
 * @return
 */
FingerprintProtocol FingerprintProtocol::makeDeleteFingerprintProtocol(uint16_t pos)
{
    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x07);
    uint8_t data[] = {0x0c, (uint8_t)(pos >> 8), (uint8_t)(pos & 0xff), 0x00, 0x01};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();
    return protocol;
}

/**
 * 删除指纹
 * @return
 */
FingerprintProtocol FingerprintProtocol::makeClearFingerprintLibProtocol(void)
{

    FingerprintProtocol protocol;
    protocol.addPacketHead();
    protocol.addPacketAddr();
    protocol.addPacketID(COMMAND_PACKET);
    protocol.addPacketLen(0x03);
    uint8_t data[] = {0x0d};
    protocol.addPacketContent(data, sizeof(data));
    protocol.addPacketSum();
    return protocol;
}
